<script setup lang="ts">
import { onMounted, ref, computed, watch } from 'vue'
import { useRoute } from 'vue-router'
import { api, toAbsoluteUrl } from '@/utils/request'

interface RankItem {
  channelId: string
  name: string
  avatarUrl: string | null
  coverUrl: string | null
  views: number
  watchSeconds: number
  giftCount?: number
  score?: number
  isManual?: boolean
}

const route = useRoute()

const period = ref<string>((route.query.period as string) || 'all')
const loading = ref(false)
const items = ref<RankItem[]>([])
const totalTopViews = ref(0)

watch(
  () => route.query.period,
  (v) => {
    period.value = (v as string) || 'all'
    fetchRanking()
  },
)

onMounted(() => {
  fetchRanking()
})

async function fetchRanking() {
  loading.value = true
  try {
    const url = `/api/live/ranking?period=${encodeURIComponent(period.value)}&limit=10&orderBy=views`
    const res = await api.get(url)
    const data = await res.json()
    items.value = (data.items || []) as RankItem[]
    totalTopViews.value = Number(data.totalTopViews || 0)
  } catch (e) {
    console.error('랭킹 가져오기 실패', e)
  } finally {
    loading.value = false
  }
}

const top5 = computed(() => {
  const list = items.value.slice(0, 5)
  const sum = list.reduce((s, x) => s + x.views, 0) || 1
  return list.map((x, i) => ({
    id: x.channelId || String(i + 1),
    name: x.name,
    views: x.views,
    ratio: `${((x.views / sum) * 100).toFixed(1)}%`,
    // 顶部卡片优先封面，其次频道头像，最后占位图
    cover:
      toAbsoluteUrl(x.coverUrl) ||
      toAbsoluteUrl(x.avatarUrl) ||
      `https://picsum.photos/seed/rank-${i}/960/360`,
    avatar:
      toAbsoluteUrl(x.avatarUrl) ||
      toAbsoluteUrl(x.coverUrl) ||
      `https://picsum.photos/seed/rank-a-${i}/120`,
  }))
})

const carouselRef = ref<HTMLElement | null>(null)
function scrollCarousel(dir: number) {
  const el = carouselRef.value as HTMLElement | null
  if (!el) return
  const card = el.querySelector('.card') as HTMLElement | null
  const step = (card?.offsetWidth || el.clientWidth) + 16 // 16≈gap
  el.scrollBy({ left: dir * step, behavior: 'smooth' })
}

const showAll = ref(false)
const visibleRanking = computed(() => (showAll.value ? ranking.value : ranking.value.slice(0, 10)))

const ranking = computed(() =>
  items.value.map((x) => ({
    id: x.channelId,
    // 表格头像用频道头像（或封面缩略）
    avatar:
      toAbsoluteUrl(x.avatarUrl) ||
      toAbsoluteUrl(x.coverUrl) ||
      `https://picsum.photos/seed/c-${x.channelId}/64`,
    name: x.name,
    views: x.views,
    giftCount: x.giftCount || 0,
    score: x.score || Math.round((x.watchSeconds || 0) / 60), // 优先使用API返回的评分，否则计算
  })),
)
</script>

<template>
  <div class="ranking-view">
    <div class="top5" ref="carouselRef">
      <button class="carousel-btn left" aria-label="prev" @click="scrollCarousel(-1)">‹</button>
      <div class="card" v-for="(u, i) in top5" :key="u.id">
        <div class="media">
          <img class="cover" :src="u.cover" />
          <div class="vignette"></div>
          <div class="badge">Top {{ i + 1 }}</div>
          <img class="avatar-overlay" :src="u.avatar" />
        </div>
        <div class="name">{{ u.name }}</div>
        <div class="meta">
          <span>시청자</span>
          <b>{{ typeof u.views === 'number' ? u.views.toLocaleString() : u.views }}</b>
          <span class="split">｜</span>
          <span>비율</span>
          <b>{{ u.ratio }}</b>
        </div>
        <div class="ratio-bar"><span :style="{ width: u.ratio }"></span></div>
      </div>
      <button class="carousel-btn right" aria-label="next" @click="scrollCarousel(1)">›</button>
    </div>

    <div class="table desktop-only">
      <div class="thead">
        <div>순위</div>
        <div>스트리머</div>
        <div>시청자</div>
        <div>선물</div>
        <div>점수</div>
      </div>
      <div class="row" v-for="(u, idx) in ranking" :key="u.id">
        <div class="col rank">
          <span class="rank-badge" :data-rank="idx + 1">{{ idx + 1 }}</span>
        </div>
        <div class="col user">
          <img :src="u.avatar" />
          <div class="n">
            <div class="title">{{ u.name }}</div>
            <div class="sub">최근 30일</div>

            <!-- 移动端表格显示更少列：仅显示排名、主播、观众 -->
          </div>
        </div>
        <div class="col">{{ u.views.toLocaleString() }}</div>
        <div class="col">
          <span class="num">{{ u.giftCount?.toLocaleString() || '0' }}</span>
          <i class="trend-dot" />
        </div>
        <div class="col score">
          <span class="val">{{ u.score }}</span>
          <span class="mini-bar"><i :style="{ width: Math.min(u.score, 100) + '%' }" /></span>
        </div>
      </div>
    </div>

    <!-- 移动端卡片列表 -->
    <div class="mobile-list mobile-only">
      <div class="m-item" v-for="(u, idx) in visibleRanking" :key="u.id">
        <div class="left">
          <span class="rank-badge" :data-rank="idx + 1">{{ idx + 1 }}</span>
          <img class="avatar" :src="u.avatar" />
        </div>
        <div class="center">
          <div class="name">{{ u.name }}</div>
          <div class="meta">
            시청자 <b>{{ u.views.toLocaleString() }}</b>
          </div>
          <div class="sub">
            최근 30일 · 선물 {{ (u.giftCount || 0).toLocaleString() }} · 점수 {{ u.score }}
          </div>
        </div>
      </div>
      <button v-if="ranking.length > 10" class="show-more" @click="showAll = !showAll">
        {{ showAll ? '접기' : '더 보기' }}
      </button>
    </div>
  </div>
</template>

<style scoped>
.ranking-view {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}

.top5 {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--space-4);
}

/* 小屏优化：卡片横向滚动而非缩到很小 */
@media (max-width: 1024px) {
  .top5 {
    position: relative;
    grid-auto-flow: column;
    grid-auto-columns: clamp(240px, 85vw, 360px);
    grid-template-columns: unset;
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x mandatory;
    padding: var(--space-2) 28px; /* 给两侧箭头预留空间 */
    gap: var(--space-3);
  }
  .top5::-webkit-scrollbar {
    display: none;
  }
  .top5 {
    -ms-overflow-style: none;
    scrollbar-width: none;
  }
  .top5 .card {
    scroll-snap-align: start;
  }

  .carousel-btn {
    display: inline-flex;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 5;
    width: 28px;
    height: 44px;
    justify-content: center;
    align-items: center;
  }
  .carousel-btn.left {
    left: 4px;
  }
  .carousel-btn.right {
    right: 4px;
  }
}

.card {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-4);
  text-align: center;
  box-shadow: var(--shadow-sm);
  transition: all 0.2s ease;
}

.card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

.card .media {
  position: relative;
}
@media (max-width: 360px) {
  .card img.cover {
    height: 132px;
  }
  .card .badge {
    font-size: 11px;
  }
  .card .avatar-overlay {
    width: 36px;
    height: 36px;
  }
}

.card img.cover {
  width: 100%;
  height: 160px;
  border-radius: var(--radius-md);
  object-fit: cover;
  display: block;
}

.card .vignette {
  position: absolute;
  inset: 0;
  border-radius: var(--radius-md);
  background: radial-gradient(
    120% 80% at 50% 40%,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0.2) 70%,
    rgba(0, 0, 0, 0.4) 100%
  );
  pointer-events: none;
}

/* 轮播按钮 */
.carousel-btn {
  position: sticky;
  align-self: center;
  top: 0;
  z-index: 2;
  width: 28px;
  height: 80px;
  margin: 0 var(--space-1);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  color: var(--color-text-secondary);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-sm);
}
.carousel-btn.left {
  left: 0;
}
.carousel-btn.right {
  right: 0;
}

@media (min-width: 1025px) {
  .carousel-btn {
    display: none;
  }
}

.card .badge {
  position: absolute;
  top: var(--space-2);
  left: var(--space-2);
  padding: var(--space-1) var(--space-2);
  font-size: 12px;
  font-weight: 600;
  border-radius: 999px;
  background: var(--gradient-primary);
  color: var(--color-text-white);
  box-shadow: var(--shadow-sm);
}

.card .avatar-overlay {
  position: absolute;
  right: var(--space-3);
  bottom: var(--space-2);
  width: 44px;
  height: 44px;
  border-radius: 50%;
  border: 2px solid var(--color-bg);
  box-shadow: var(--shadow-md);
  object-fit: cover;
  background: var(--color-bg);
}

.card .ratio-bar {
  height: 6px;
  background: var(--color-border-light);
  border-radius: 999px;
  margin-top: var(--space-2);
  overflow: hidden;
}

.card .ratio-bar span {
  display: block;
  height: 100%;
  background: var(--gradient-primary);
  border-radius: 999px;
}

.card .name {
  color: var(--color-text);
  margin-top: var(--space-2);
  font-weight: 600;
}

/* 桌面/移动可见性控制 */
.desktop-only {
  display: block;
}
.mobile-only {
  display: none;
}
@media (max-width: 768px) {
  .desktop-only {
    display: none;
  }
  .mobile-only {
    display: block;
  }
}

/* 移动端卡片列表样式 */
.mobile-list {
  margin-top: var(--space-2);
}
.m-item {
  display: flex;
  gap: var(--space-3);
  align-items: center;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-3);
  box-shadow: var(--shadow-sm);
}
.m-item + .m-item {
  margin-top: var(--space-2);
}
.m-item .left {
  display: flex;
  gap: var(--space-2);
  align-items: center;
}
.m-item .avatar {
  width: 36px;
  height: 36px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--color-border);
}
.m-item .center .name {
  font-weight: 600;
  color: var(--color-text);
}
.m-item .center .meta {
  color: var(--color-text-secondary);
  font-size: 12px;
}
.m-item .center .meta b {
  color: var(--color-primary);
}
.m-item .center .sub {
  color: var(--color-text-muted);
  font-size: 11px;
  margin-top: 2px;
}
.show-more {
  width: 100%;
  margin-top: var(--space-2);
  padding: var(--space-2) 0;
  border-radius: var(--radius-md);
  border: 1px solid var(--color-border);
  background: var(--color-surface);
}

.card .meta {
  color: var(--color-text-secondary);
  font-size: 12px;
  margin-top: var(--space-2);
  display: flex;
  align-items: center;
  gap: var(--space-2);
  justify-content: center;
}

.card .meta b {
  color: var(--color-primary);
}

.card .meta .split {
  opacity: 0.5;
}

.table {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
  /* 允许小屏横向滚动，避免表格挤压变形 */
  overflow: auto;
  -webkit-overflow-scrolling: touch;
}

.thead,
.row {
  display: grid;
  grid-template-columns: 80px 1fr 120px 120px 160px;
  align-items: center;
  padding: var(--space-4);
  gap: var(--space-2);
  min-width: 720px; /* 防止列过窄导致换行 */
}

.thead {
  color: var(--color-text-secondary);
  background: var(--color-surface);
  border-bottom: 1px solid var(--color-border);
  font-weight: 600;
}

.row {
  color: var(--color-text);
  border-top: 1px solid var(--color-border-light);
  transition: background 0.2s ease;
}

.row:hover {
  background: var(--color-surface-hover);
}

.row .user {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.row .user img {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
  border: 2px solid var(--color-border);
  box-shadow: var(--shadow-sm);
}

.rank-badge {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--color-border);
  background: var(--color-surface);
  font-weight: 600;
  color: var(--color-text);
}

.rank-badge[data-rank='1'] {
  background: linear-gradient(180deg, #fde68a, #eab308);
  color: #111;
  border-color: #eab308;
}

.rank-badge[data-rank='2'] {
  background: linear-gradient(180deg, #e5e7eb, #9ca3af);
  color: #111;
  border-color: #9ca3af;
}

.rank-badge[data-rank='3'] {
  background: linear-gradient(180deg, #fcd5b5, #d97706);
  color: #111;
  border-color: #d97706;
}

.score .val {
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  color: var(--color-primary);
}

.score .mini-bar {
  display: inline-block;
  width: 90px;
  height: 6px;
  background: var(--color-border-light);
  border-radius: 999px;
  margin-left: var(--space-2);
  vertical-align: middle;
}

.score .mini-bar i {
  display: block;
  height: 100%;
  background: var(--gradient-primary);
  border-radius: 999px;
}

.trend-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  background: var(--color-primary);
  border-radius: 50%;
  margin-left: var(--space-2);
}

/* 移动端响应式设计 */
@media (max-width: 768px) {
  .ranking-view {
    gap: var(--space-4);
  }

  /* 顶部五强：改为横滑卡片，已在上方 @media 里处理 */

  .card img.cover {
    height: 140px;
  }

  .card .name {
    font-size: 14px;
  }

  .card .meta {
    font-size: 11px;
  }

  /* 表格：在小屏显示为滚动容器，行列保持宽度 */
  .thead,
  .row {
    padding: var(--space-3);
  }
}

@media (max-width: 480px) {
  .ranking-view {
    gap: var(--space-3);
  }

  .grid {
    grid-template-columns: 1fr;
    gap: var(--space-3);
  }

  .card {
    padding: var(--space-3);
  }

  .card img.cover {
    height: 160px;
  }

  .card .name {
    font-size: 15px;
    margin-top: var(--space-2);
  }

  .card .meta {
    font-size: 12px;
    margin-top: var(--space-1);
  }

  .card .badge {
    top: var(--space-2);
    left: var(--space-2);
    font-size: 11px;
    padding: 2px var(--space-1);
  }

  .card .avatar-overlay {
    right: var(--space-2);
    bottom: var(--space-2);
    width: 32px;
    height: 32px;
  }
}
</style>
